﻿using Castle.DynamicProxy;
using Common.Core.Exceptions;
using Simple.Common.Core.Hosting;
using Simple.Common.Uow.Uow;
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Simple.Common.Application.CastleIntercepts
{
    public class UowInterceptor : IAsyncInterceptor
    {
        public void InterceptAsynchronous(IInvocation invocation)
        {
            //获取当前工作单元，存在新增db，不存在初始化巩工作单元
            var uow = ServiceProviderHelper.GetService<IUnitOfWork>();
            //调用业务方法
            invocation.Proceed();
        }
        /// <summary>
        /// 异步方法返回Task<T>时使用
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="invocation"></param>
        public void InterceptAsynchronous<TResult>(IInvocation invocation)
        {
            //获取当前工作单元，存在新增db，不存在初始化巩工作单元
            var unitOfWork = ServiceProviderHelper.GetService<IUnitOfWork>();
            //调用业务方法
            invocation.Proceed();
            //调用业务方法
            invocation.ReturnValue = InternalInterceptAsynchronous<TResult>(invocation, unitOfWork);
        }
        /// <summary>
        /// 业务执行
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="invocation"></param>
        /// <param name="unitOfWork"></param>
        /// <returns></returns>
        private async Task<TResult> InternalInterceptAsynchronous<TResult>(IInvocation invocation,IUnitOfWork unitOfWork)
        {
            try
            {
                MethodInfo methodInfo = invocation.MethodInvocationTarget;
                if (methodInfo == null)
                    methodInfo = invocation.Method;
                if (methodInfo.DeclaringType.Name.Contains(""))
                {
                    await unitOfWork.CommitAsync();

                }
                Task<TResult> task = (Task<TResult>)invocation.ReturnValue;
                TResult result = await task;//获得返回结果
                return result;
            }
            catch (Exception e)
            {
                var str=await GetMethodInfo(invocation);
                throw new BusinessException(str,e);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="invocation"></param>
        public void InterceptSynchronous(IInvocation invocation)
        {

        }
        /// <summary>
        /// 获取拦截方法信息（类名、方法名、参数）
        /// </summary>
        /// <param name="invocation"></param>
        /// <returns></returns>
        private async Task<string> GetMethodInfo(IInvocation invocation)
        {
            try
            {
                var str = "";
                //方法类名
                string className = invocation.Method.DeclaringType.Name;
                //方法名
                string methodName = invocation.Method.Name;
                //参数
                string args = string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray());


                if (string.IsNullOrWhiteSpace(args))
                {
                    str= $"{className}.{methodName}";
                }
                else
                {
                    str= $"{className}.{methodName}:{args}";
                }
                return await Task.FromResult(str);
            }
            catch (Exception e)
            {
                throw new BusinessException("工作单元拦截器获取方法错误", e);
            }
            
        }
    }
}
